home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / linkedit / linkedit.lha / link-edit / LinkEdit / Choose / glob.c.old < prev    next >
Encoding:
Text File  |  1991-03-13  |  10.2 KB  |  677 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)glob.c    5.7 (Berkeley) 12/14/88";
  20. #endif /* not lint */
  21.  
  22. /*
  23.  * C-shell glob for random programs.
  24.  */
  25.  
  26. #include <sys/param.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <dirent.h>
  30.  
  31. #include <stdio.h>
  32. #include <errno.h>
  33. #include <pwd.h>
  34.  
  35. #define    QUOTE 0200
  36. #define    TRIM 0177
  37. #define    eq(a,b)        (strcmp(a, b)==0)
  38. #define    GAVSIZ        (NCARGS/6)
  39. #define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  40.  
  41. static    char **gargv;        /* Pointer to the (stack) arglist */
  42. static    int gargc;        /* Number args in gargv */
  43. static    int gnleft;
  44. static    short gflag;
  45. static    int tglob();
  46. char    **glob();
  47. char    *globerr;
  48. char    *home;
  49. struct    passwd *getpwnam();
  50. extern    int errno;
  51. static    char *strspl(), *strend();
  52. char    *malloc(), *strcpy(), *strcat();
  53. char    **copyblk();
  54.  
  55. static    int globcnt;
  56.  
  57. char    *globchars = "`{[*?";
  58.  
  59. static    char *gpath, *gpathp, *lastgpathp;
  60. static    int globbed;
  61. static    char *entp;
  62. static    char **sortbas;
  63.  
  64. char **
  65. glob(v)
  66.     register char *v;
  67. {
  68.     char agpath[BUFSIZ];
  69.     char *agargv[GAVSIZ];
  70.     char *vv[2];
  71.     vv[0] = v;
  72.     vv[1] = 0;
  73.     gflag = 0;
  74.     rscan(vv, tglob);
  75.     if (gflag == 0)
  76.         return (copyblk(vv));
  77.  
  78.     globerr = 0;
  79.     gpath = agpath; gpathp = gpath; *gpathp = 0;
  80.     lastgpathp = &gpath[sizeof agpath - 2];
  81.     ginit(agargv); globcnt = 0;
  82.     collect(v);
  83.     if (globcnt == 0 && (gflag&1)) {
  84.         blkfree(gargv), gargv = 0;
  85.         return (0);
  86.     } else
  87.         return (gargv = copyblk(gargv));
  88. }
  89.  
  90. static
  91. ginit(agargv)
  92.     char **agargv;
  93. {
  94.  
  95.     agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  96.     gnleft = NCARGS - 4;
  97. }
  98.  
  99. static
  100. collect(as)
  101.     register char *as;
  102. {
  103.     if (eq(as, "{") || eq(as, "{}")) {
  104.         Gcat(as, "");
  105.         sort();
  106.     } else
  107.         acollect(as);
  108. }
  109.  
  110. static
  111. acollect(as)
  112.     register char *as;
  113. {
  114.     register int ogargc = gargc;
  115.  
  116.     gpathp = gpath; *gpathp = 0; globbed = 0;
  117.     expand(as);
  118.     if (gargc != ogargc)
  119.         sort();
  120. }
  121.  
  122. static
  123. sort()
  124. {
  125.     register char **p1, **p2, *c;
  126.     char **Gvp = &gargv[gargc];
  127.  
  128.     p1 = sortbas;
  129.     while (p1 < Gvp-1) {
  130.         p2 = p1;
  131.         while (++p2 < Gvp)
  132.             if (strcmp(*p1, *p2) > 0)
  133.                 c = *p1, *p1 = *p2, *p2 = c;
  134.         p1++;
  135.     }
  136.     sortbas = Gvp;
  137. }
  138.  
  139. static
  140. expand(as)
  141.     char *as;
  142. {
  143.     register char *cs;
  144.     register char *sgpathp, *oldcs;
  145.     struct stat stb;
  146.  
  147.     sgpathp = gpathp;
  148.     cs = as;
  149.     if (*cs == '~' && gpathp == gpath) {
  150.         addpath('~');
  151.         for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  152.             addpath(*cs++);
  153.         if (!*cs || *cs == '/') {
  154.             if (gpathp != gpath + 1) {
  155.                 *gpathp = 0;
  156.                 if (gethdir(gpath + 1))
  157.                     globerr = "Unknown user name after ~";
  158.                 (void) strcpy(gpath, gpath + 1);
  159.             } else
  160.                 (void) strcpy(gpath, home);
  161.             gpathp = strend(gpath);
  162.         }
  163.     }
  164.     while (!any(*cs, globchars)) {
  165.         if (*cs == 0) {
  166.             if (!globbed)
  167.                 Gcat(gpath, "");
  168.             else if (stat(gpath, &stb) >= 0) {
  169.                 Gcat(gpath, "");
  170.                 globcnt++;
  171.             }
  172.             goto endit;
  173.         }
  174.         addpath(*cs++);
  175.     }
  176.     oldcs = cs;
  177.     while (cs > as && *cs != '/')
  178.         cs--, gpathp--;
  179.     if (*cs == '/')
  180.         cs++, gpathp++;
  181.     *gpathp = 0;
  182.     if (*oldcs == '{') {
  183.         (void) execbrc(cs, ((char *)0));
  184.         return;
  185.     }
  186.     matchdir(cs);
  187. endit:
  188.     gpathp = sgpathp;
  189.     *gpathp = 0;
  190. }
  191.  
  192. static
  193. matchdir(pattern)
  194.     char *pattern;
  195. {
  196.     struct stat stb;
  197.     register struct dirent *dp;
  198.     DIR *dirp;
  199.  
  200.     dirp = opendir(gpath[0] == '\0' ? "." : gpath);
  201.     if (dirp == NULL) {
  202.         if (globbed)
  203.             return;
  204.         goto patherr2;
  205.     }
  206.     if (fstat(dirp->dd_fd, &stb) < 0)
  207.         goto patherr1;
  208.     if (!isdir(stb)) {
  209.         errno = ENOTDIR;
  210.         goto patherr1;
  211.     }
  212.     while ((dp = readdir(dirp)) != NULL) {
  213.         if (dp->d_ino == 0)
  214.             continue;
  215.         if (match(dp->d_name, pattern)) {
  216.             Gcat(gpath, dp->d_name);
  217.             globcnt++;
  218.         }
  219.     }
  220.     closedir(dirp);
  221.     return;
  222.  
  223. patherr1:
  224.     closedir(dirp);
  225. patherr2:
  226.     globerr = "Bad directory components";
  227. }
  228.  
  229. static
  230. execbrc(p, s)
  231.     char *p, *s;
  232. {
  233.     char restbuf[BUFSIZ + 2];
  234.     register char *pe, *pm, *pl;
  235.     int brclev = 0;
  236.     char *lm, savec, *sgpathp;
  237.  
  238.     for (lm = restbuf; *p != '{'; *lm++ = *p++)
  239.         continue;
  240.     for (pe = ++p; *pe; pe++)
  241.     switch (*pe) {
  242.  
  243.     case '{':
  244.         brclev++;
  245.         continue;
  246.  
  247.     case '}':
  248.         if (brclev == 0)
  249.             goto pend;
  250.         brclev--;
  251.         continue;
  252.  
  253.     case '[':
  254.         for (pe++; *pe && *pe != ']'; pe++)
  255.             continue;
  256.         continue;
  257.     }
  258. pend:
  259.     brclev = 0;
  260.     for (pl = pm = p; pm <= pe; pm++)
  261.     switch (*pm & (QUOTE|TRIM)) {
  262.  
  263.     case '{':
  264.         brclev++;
  265.         continue;
  266.  
  267.     case '}':
  268.         if (brclev) {
  269.             brclev--;
  270.             continue;
  271.         }
  272.         goto doit;
  273.  
  274.     case ','|QUOTE:
  275.     case ',':
  276.         if (brclev)
  277.             continue;
  278. doit:
  279.         savec = *pm;
  280.         *pm = 0;
  281.         (void) strcpy(lm, pl);
  282.         (void) strcat(restbuf, pe + 1);
  283.         *pm = savec;
  284.         if (s == 0) {
  285.             sgpathp = gpathp;
  286.             expand(restbuf);
  287.             gpathp = sgpathp;
  288.             *gpathp = 0;
  289.         } else if (amatch(s, restbuf))
  290.             return (1);
  291.         sort();
  292.         pl = pm + 1;
  293.         if (brclev)
  294.             return (0);
  295.         continue;
  296.  
  297.     case '[':
  298.         for (pm++; *pm && *pm != ']'; pm++)
  299.             continue;
  300.         if (!*pm)
  301.             pm--;
  302.         continue;
  303.     }
  304.     if (brclev)
  305.         goto doit;
  306.     return (0);
  307. }
  308.  
  309.  
  310. match(s, p)
  311.     char *s, *p;
  312. {
  313.     register int c;
  314.     register char *sentp;
  315.     char sglobbed = globbed;
  316.  
  317.     if (*s == '.' && *p != '.')
  318.         return (0);
  319.     sentp = entp;
  320.     entp = s;
  321.     c = amatch(s, p);
  322.     entp = sentp;
  323.     globbed = sglobbed;
  324.     return (c);
  325. }
  326.  
  327. static
  328. amatch(s, p)
  329.     register char *s, *p;
  330. {
  331.     register int scc;
  332.     int ok, lc;
  333.     char *sgpathp;
  334.     struct stat stb;
  335.     int c, cc;
  336.  
  337.     globbed = 1;
  338.     for (;;) {
  339.         scc = *s++ & TRIM;
  340.         switch (c = *p++) {
  341.  
  342.         case '{':
  343.             return (execbrc(p - 1, s - 1));
  344.  
  345.         case '[':
  346.             ok = 0;
  347.             lc = 077777;
  348.             while (cc = *p++) {
  349.                 if (cc == ']') {
  350.                     if (ok)
  351.                         break;
  352.                     return (0);
  353.                 }
  354.                 if (cc == '-') {
  355.                     if (lc <= scc && scc <= *p++)
  356.                         ok++;
  357.                 } else
  358.                     if (scc == (lc = cc))
  359.                         ok++;
  360.             }
  361.             if (cc == 0)
  362.                 if (ok)
  363.                     p--;
  364.                 else
  365.                     return 0;
  366.             continue;
  367.  
  368.         case '*':
  369.             if (!*p)
  370.                 return (1);
  371.             if (*p == '/') {
  372.                 p++;
  373.                 goto slash;
  374.             }
  375.             s--;
  376.             do {
  377.                 if (amatch(s, p))
  378.                     return (1);
  379.             } while (*s++);
  380.             return (0);
  381.  
  382.         case 0:
  383.             return (scc == 0);
  384.  
  385.         default:
  386.             if (c != scc)
  387.                 return (0);
  388.             continue;
  389.  
  390.         case '?':
  391.             if (scc == 0)
  392.                 return (0);
  393.             continue;
  394.  
  395.         case '/':
  396.             if (scc)
  397.                 return (0);
  398. slash:
  399.             s = entp;
  400.             sgpathp = gpathp;
  401.             while (*s)
  402.                 addpath(*s++);
  403.             addpath('/');
  404.             if (stat(gpath, &stb) == 0 && isdir(stb))
  405.                 if (*p == 0) {
  406.                     Gcat(gpath, "");
  407.                     globcnt++;
  408.                 } else
  409.                     expand(p);
  410.             gpathp = sgpathp;
  411.             *gpathp = 0;
  412.             return (0);
  413.         }
  414.     }
  415. }
  416.  
  417. static
  418. Gmatch(s, p)
  419.     register char *s, *p;
  420. {
  421.     register int scc;
  422.     int ok, lc;
  423.     int c, cc;
  424.  
  425.     for (;;) {
  426.         scc = *s++ & TRIM;
  427.         switch (c = *p++) {
  428.  
  429.         case '[':
  430.             ok = 0;
  431.             lc = 077777;
  432.             while (cc = *p++) {
  433.                 if (cc == ']') {
  434.                     if (ok)
  435.                         break;
  436.                     return (0);
  437.                 }
  438.                 if (cc == '-') {
  439.                     if (lc <= scc && scc <= *p++)
  440.                         ok++;
  441.                 } else
  442.                     if (scc == (lc = cc))
  443.                         ok++;
  444.             }
  445.             if (cc == 0)
  446.                 if (ok)
  447.                     p--;
  448.                 else
  449.                     return 0;
  450.             continue;
  451.  
  452.         case '*':
  453.             if (!*p)
  454.                 return (1);
  455.             for (s--; *s; s++)
  456.                 if (Gmatch(s, p))
  457.                     return (1);
  458.             return (0);
  459.  
  460.         case 0:
  461.             return (scc == 0);
  462.  
  463.         default:
  464.             if ((c & TRIM) != scc)
  465.                 return (0);
  466.             continue;
  467.  
  468.         case '?':
  469.             if (scc == 0)
  470.                 return (0);
  471.             continue;
  472.  
  473.         }
  474.     }
  475. }
  476.  
  477. static
  478. Gcat(s1, s2)
  479.     register char *s1, *s2;
  480. {
  481.     register int len = strlen(s1) + strlen(s2) + 1;
  482.  
  483.     if (len >= gnleft || gargc >= GAVSIZ - 1)
  484.         globerr = "Arguments too long";
  485.     else {
  486.         gargc++;
  487.         gnleft -= len;
  488.         gargv[gargc] = 0;
  489.         gargv[gargc - 1] = strspl(s1, s2);
  490.     }
  491. }
  492.  
  493. static
  494. addpath(c)
  495.     char c;
  496. {
  497.  
  498.     if (gpathp >= lastgpathp)
  499.         globerr = "Pathname too long";
  500.     else {
  501.         *gpathp++ = c;
  502.         *gpathp = 0;
  503.     }
  504. }
  505.  
  506. static
  507. rscan(t, f)
  508.     register char **t;
  509.     int (*f)();
  510. {
  511.     register char *p, c;
  512.  
  513.     while (p = *t++) {
  514.         if (f == tglob)
  515.             if (*p == '~')
  516.                 gflag |= 2;
  517.             else if (eq(p, "{") || eq(p, "{}"))
  518.                 continue;
  519.         while (c = *p++)
  520.             (*f)(c);
  521.     }
  522. }
  523. /*
  524. static
  525. scan(t, f)
  526.     register char **t;
  527.     int (*f)();
  528. {
  529.     register char *p, c;
  530.  
  531.     while (p = *t++)
  532.         while (c = *p)
  533.             *p++ = (*f)(c);
  534. } */
  535.  
  536. static
  537. tglob(c)
  538.     register char c;
  539. {
  540.  
  541.     if (any(c, globchars))
  542.         gflag |= c == '{' ? 2 : 1;
  543.     return (c);
  544. }
  545. /*
  546. static
  547. trim(c)
  548.     char c;
  549. {
  550.  
  551.     return (c & TRIM);
  552. } */
  553.  
  554.  
  555. letter(c)
  556.     register char c;
  557. {
  558.  
  559.     return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
  560. }
  561.  
  562. digit(c)
  563.     register char c;
  564. {
  565.  
  566.     return (c >= '0' && c <= '9');
  567. }
  568.  
  569. any(c, s)
  570.     register int c;
  571.     register char *s;
  572. {
  573.  
  574.     while (*s)
  575.         if (*s++ == c)
  576.             return(1);
  577.     return(0);
  578. }
  579. blklen(av)
  580.     register char **av;
  581. {
  582.     register int i = 0;
  583.  
  584.     while (*av++)
  585.         i++;
  586.     return (i);
  587. }
  588.  
  589. char **
  590. blkcpy(oav, bv)
  591.     char **oav;
  592.     register char **bv;
  593. {
  594.     register char **av = oav;
  595.  
  596.     while (*av++ = *bv++)
  597.         continue;
  598.     return (oav);
  599. }
  600.  
  601. blkfree(av0)
  602.     char **av0;
  603. {
  604.     register char **av = av0;
  605.  
  606.     while (*av)
  607.         free(*av++);
  608. }
  609.  
  610. static
  611. char *
  612. strspl(cp, dp)
  613.     register char *cp, *dp;
  614. {
  615.     register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
  616.  
  617.     if (ep == (char *)0)
  618.         fatal("Out of memory");
  619.     (void) strcpy(ep, cp);
  620.     (void) strcat(ep, dp);
  621.     return (ep);
  622. }
  623.  
  624. char **
  625. copyblk(v)
  626.     register char **v;
  627. {
  628.     register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
  629.                         sizeof(char **)));
  630.     if (nv == (char **)0)
  631.         fatal("Out of memory");
  632.  
  633.     return (blkcpy(nv, v));
  634. }
  635.  
  636. static
  637. char *
  638. strend(cp)
  639.     register char *cp;
  640. {
  641.  
  642.     while (*cp)
  643.         cp++;
  644.     return (cp);
  645. }
  646. /*
  647.  * Extract a home directory from the password file
  648.  * The argument points to a buffer where the name of the
  649.  * user whose home directory is sought is currently.
  650.  * We write the home directory of the user back there.
  651.  */
  652. gethdir(home)
  653.     char *home;
  654. {
  655.     register struct passwd *pp = getpwnam(home);
  656.  
  657.     if (!pp || home + strlen(pp->pw_dir) >= lastgpathp)
  658.         return (1);
  659.     (void) strcpy(home, pp->pw_dir);
  660.     return (0);
  661. }
  662.  
  663. static
  664. fatal(s)
  665. char *s;
  666. {
  667.     fprintf( stderr, "glob: %s\n", s );
  668.     exit(1);
  669. }
  670. /*
  671. main()
  672.  
  673. { printf(" %4d \n", match("Yo","*"));
  674.  printf(" %4d \n", match("*","Yo"));
  675.  printf(" %4d \n", match("You","Y*"));
  676. }
  677. */